package com.xcc.dataStructures.demo04_stack;

/**
 * 中缀表达式
 *
 * @author xiaocheng
 * @date 2020/11/25 15:55
 */
public class Calculator {

    public static void main(String[] args) {
        String expression = "7*2*100/5+3-4"; // 18//如何处理多位数的问题？
        ArrayStack nums = new ArrayStack(10);
        ArrayStack opers = new ArrayStack(10);
        int index = 0;
        int num1 = 0;
        int num2 = 0;
        int oper = 0; //运算符
        int res = 0;
        char ch = ' ';
        String str = "";//多位数数值
        while (true) {
            ch = expression.substring(index, index + 1).charAt(0); //获取当前的字符
            if (opers.isOper(ch)) { //扫描到符号
                if (opers.isEmpty()) {
                    //符号栈为空就直接入栈
                    opers.push(ch);
                } else {
                    //查看符号栈栈顶的优先级
                    int stackpri = opers.priority(opers.peek());
                    //查看当前符号的优先级
                    int chpri = opers.priority(ch);
                    //如果当前符号优先级 小于等于 符号栈栈顶的优先级 则计算数字栈的两个数字并压栈到数字栈 将当前符合压入符号栈
                    if (chpri <= stackpri) {
                        num2 = nums.pop();
                        num1 = nums.pop();
                        oper = opers.pop();
                        res = nums.cal(num1, num2, oper);
                        nums.push(res);
                        opers.push(ch);
                    } else {
                        //如果当前符号 大于 符号栈栈顶的优先级  则直接入栈
                        opers.push(ch);
                    }
                }
            } else {
                //扫描到数字
                str += ch ;
                if (index == (expression.length() - 1)) {
                    nums.push(Integer.parseInt(str));
                } else {
                    char next = expression.substring(index + 1, index + 2).charAt(0);
                    //如果下一个char是符号
                    if (opers.isOper(next)) {
                        nums.push(Integer.parseInt(str));
                        str = "";
                    }
                }
            }
            if (index + 1 >= expression.length()) {
                break;
            }
            index++;
        }

        num2 = nums.pop();
        num1 = nums.pop();
        int result = nums.cal(num1, num2, opers.pop());
        System.out.println("最终结果为：" + result);
    }

}

class ArrayStack {

    private int maxSize;
    private int[] arr;
    private int top = -1;

    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        this.arr = new int[maxSize];
    }

    /**
     * 往栈中push数据
     */
    public void push(int val) {
        if (isFull()) {
            System.out.println("栈满了，无法插入数据!");
            return;
        }
        arr[++top] = val;
    }

    /**
     * 判断满
     */
    public boolean isFull() {
        return top == maxSize - 1;
    }

    /**
     * 获取
     */
    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈空了，无法取到数据");
        }
        return arr[top--];
    }

    /**
     * 打印栈
     */
    public void show() {
        for (int i = top; i >= 0; i--) {
            System.out.printf("arr[%d] = %d\n", i, arr[i]);
        }
    }

    /**
     * 判空
     */
    public boolean isEmpty() {
        return top < 0;
    }

    /**
     * 查看
     */
    public int peek() {
        if (isEmpty()) {
            throw new RuntimeException("栈空了，无法取到数据");
        }
        return arr[top];
    }

    public boolean isOper(char ch) {
        return ch == '*' || ch == '/' || ch == '+' || ch == '-';
    }

    /**
     * 比较运算符的优先级
     */
    public int priority(int oper) {
        if ('*' == oper || '/' == oper) {
            return 1;
        } else if ('-' == oper || '+' == oper) {
            return 0;
        } else {
            return -1;
        }
    }

    public int cal(int num1, int num2, int oper) {
        int res = 0;
        switch (oper) {
            case '*':
                res = num1 * num2;
                break;
            case '/':
                res = num1 / num2;
                break;
            case '+':
                res = num1 + num2;
                break;
            case '-':
                res = num1 - num2;
                break;
        }
        return res;
    }
}